#include "myCAN\myCAN.h"

#if (STM32CUBEMX==1)
CAN_HandleTypeDef hcan;

/*
 * @brief  CAN GPIO初始化函数
 * @param(CAN_HandleTypeDef* canHandle):CAN句柄,V1_0_0版本只兼容CAN1资源
 * @作者: 跳河轻生的鱼
 * @日期: 2024-12-17
 * @接收GPIO: PB8
 * @发送GPIO: PB9
 */
void myHAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_CAN1_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**CAN GPIO Configuration
    PB8     ------> CAN_RX
    PB9     ------> CAN_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    __HAL_AFIO_REMAP_CAN1_2();
}

/*
 * @brief  CAN初始化函数
 * @param  hcan: CAN句柄
 * @作者: 跳河轻生的鱼
 * @日期: 2024-12-17
 * @note:  配置为环回模式
 * @retval 无
 * @接收GPIO: PB8
 * @发送GPIO: PB9
 */
void myHAL_CAN_Init(void)
{

        //配置过滤器
    CAN_FilterTypeDef filterConfig;

    myHAL_CAN_MspInit(&hcan);
    hcan.Instance = CAN1;                     //选择外设资源
    hcan.Init.Mode = CAN_MODE_NORMAL;       //配置为环回模式
    hcan.Init.Prescaler = 48;                 //配置分频系数                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
    hcan.Init.TimeSeg1 = CAN_BS1_2TQ;         //配置BS1的宽度
    hcan.Init.TimeSeg2 = CAN_BS2_3TQ;         //配置BS2的宽度
    hcan.Init.SyncJumpWidth = CAN_SJW_2TQ;    //配置SJW的宽度
    hcan.Init.AutoRetransmission = ENABLE;    //配置为自动重传模式
    hcan.Init.TimeTriggeredMode = DISABLE;    //配置为非时间触发模式
    hcan.Init.AutoBusOff = DISABLE;           //配置为禁用自动离线模式
    hcan.Init.AutoWakeUp = DISABLE;           //配置为手动唤醒模式
    hcan.Init.ReceiveFifoLocked = DISABLE;    //配置为禁用锁定模式，FIFO溢出时接收新报文不会进入堵塞
    hcan.Init.TransmitFifoPriority = DISABLE; //配置为优先级模式
    HAL_CAN_Init(&hcan);

    filterConfig.SlaveStartFilterBank = 0;                  // 选择过滤器起始编号 对于单个CAN该参数无意义
    filterConfig.FilterBank = 0;                            // 选择过滤器编号0
    filterConfig.FilterMode = CAN_FILTERMODE_IDMASK;        // 过滤器模式：ID掩码模式
    filterConfig.FilterScale = CAN_FILTERSCALE_32BIT;       // 32 位过滤器
    filterConfig.FilterIdHigh = 0x0000;                     // 过滤器标准ID高16位
    filterConfig.FilterIdLow = 0x0000;                      // 过滤器标准ID低16位
    filterConfig.FilterMaskIdHigh = 0x0000;                 // 过滤器掩码高16位
    filterConfig.FilterMaskIdLow = 0x0000;                  // 过滤器掩码低16位
    filterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;   // 选择FIFO
    filterConfig.FilterActivation = ENABLE;                 // 启用过滤器
    HAL_CAN_ConfigFilter(&hcan, &filterConfig);
    // 3. 启动 CAN 接收和发送
    HAL_CAN_Start(&hcan);

}
#endif





/*
 * @brief  CAN发送函数
 * @param  hcan: CAN句柄
 * @param  StdId: 标准帧ID
 * @param  pData: 数据指针
 * @param  Len: 数据长度
 * @作者: 跳河轻生的鱼
 * @日期: 2024-12-14
 */
void myCAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t StdId, uint8_t *pData, uint8_t Len)
{
    CAN_TxHeaderTypeDef TxHeader;
    uint32_t Timeout = 0;
    uint32_t pTxMailbox;
    TxHeader.StdId = StdId;                                    // 标准帧ID
    TxHeader.RTR = CAN_RTR_DATA;                               // 数据帧
    TxHeader.IDE = CAN_ID_STD;                                 // 标准帧
    TxHeader.DLC = Len;                                        // 数据长度
    while(HAL_CAN_AddTxMessage(hcan, &TxHeader, pData, &pTxMailbox) != HAL_OK)
    {
        Timeout++;
        /* 超时处理 */
        if(Timeout > 100000)//大概7200为100us
        {
            break;
        }
        
    }
}


uint8_t myCAN_Receive(CAN_HandleTypeDef *hcan, uint32_t *StdId, uint8_t *pData, uint8_t *Len)
{
    CAN_RxHeaderTypeDef RxHeader;
    uint32_t fifoLevel = HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0);  // 获取 FIFO0 的接收消息数量
    if (fifoLevel>0)  // 检查 FIFO0 是否有接收到的消息
    {
        if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, pData) == HAL_OK)
        {
            // 处理接收到的消息
            // RxHeader 包含消息头信息（如ID、DLC等）
            *StdId = (RxHeader.IDE == CAN_ID_STD) ? RxHeader.StdId : RxHeader.ExtId;
            // RxData 是接收到的数据
            *Len = RxHeader.DLC;
        }
				return 1;
    }
		return 0;


}


/*
 * 函数名称：void myCAN_LoopBockTest(void)
 * 函数功能：CAN通信任务
 * 输入参数：无
 * 返回值：无
 * 作者：跳河轻生的鱼
 * 创建日期：2024-12-13
 * 修改日期：无
 * 修改原因：无
 * 版本号：1.0.0
 * 注意事项：无
 */
void myCAN_LoopBockTest(void)
{
    uint32_t RxID;
    uint8_t RxLength;
    uint8_t RxData[8];

    uint32_t TxID = 0x666;
    uint8_t TxLength = 4;

    uint8_t TxData[8] = {0x11, 0x22, 0x33, 0x44};

    /* Infinite loop */

    MySpi_OLED_Clean();
    MySpi_OLED_ShowString(1,1,"TxID:");
    MySpi_OLED_ShowHexNum(1,6,TxID,3);
    MySpi_OLED_ShowString(2,1,"RxID:");
    MySpi_OLED_ShowString(4,1,"RxDa:");
    MySpi_OLED_ShowString(5,1,"RxLe:");
    for(;;)
    {
        TxData[0] ++;
        TxData[1] ++;
        TxData[2] ++;
        TxData[3] ++;
        myCAN_Transmit(&hcan ,TxID, TxData, TxLength);
        myCAN_Receive(&hcan, &RxID, RxData, &RxLength);
        MySpi_OLED_ShowHexNum(2,6,RxID,3);
        MySpi_OLED_ShowHexNum(3,6,RxData[0],2);
        MySpi_OLED_ShowHexNum(3,9,RxData[1],2);
        MySpi_OLED_ShowHexNum(3,12,RxData[2],2);
        MySpi_OLED_ShowHexNum(3,15,RxData[3],2);
        MySpi_OLED_ShowNum(4,6,RxLength,2);

        delay_ms(2000);
    }
}

/*
 * 函数名称：void myCAN_LoopBockTest(void)
 * 函数功能：CAN通信任务
 * 输入参数：无
 * 返回值：无
 * 作者：跳河轻生的鱼
 * 创建日期：2024-12-13
 * 修改日期：无
 * 修改原因：无
 * 版本号：1.0.0
 * 注意事项：无
 */
void myCAN_NORMALTest(void)
{
    uint32_t RxID;
    uint8_t RxLength;
    uint8_t RxData[8];
    uint8_t a = 0;
    uint32_t TxID = 0x666;
    uint8_t TxLength = 4;
		int ts = 0;
		CAN_T_DATA txdata;
    uint8_t TxData[8] = {0x11, 0x22, 0x33, 0x44};
    MySpi_OLED_Clean();
    MySpi_OLED_ShowString(1,1,"TxID:");
    MySpi_OLED_ShowHexNum(1,6,TxID,3);
    MySpi_OLED_ShowString(2,1,"RxID:");
    MySpi_OLED_ShowString(4,1,"RxDa:");
    MySpi_OLED_ShowString(5,1,"RxLe:");
    for(;;)
    {
        a = KEY_Scan(1);
        if(a == 1)
        {
					  txdata.angle ++;
						MySpi_OLED_ShowNum(4,9,txdata.angle,3);
            
        }
				if(a == 2)
				{
						txdata.angle --;
						MySpi_OLED_ShowNum(4,9,txdata.angle,3);
				}
				if(a == 3)
				{
						
						txdata.flag = 1;
						myCAN_Transmit(&hcan ,TxID, (uint8_t *)&txdata, TxLength);
				}
				if(a == 4)
				{
			
						txdata.flag = 1;
						myCAN_Transmit(&hcan ,TxID, (uint8_t *)&txdata, TxLength);
				}
        myCAN_Receive(&hcan, &RxID, RxData, &RxLength);
        MySpi_OLED_ShowHexNum(2,6,RxID,3);
        MySpi_OLED_ShowHexNum(3,6,RxData[0],2);
        MySpi_OLED_ShowHexNum(3,9,RxData[1],2);
        MySpi_OLED_ShowHexNum(3,12,RxData[2],2);
        MySpi_OLED_ShowHexNum(3,15,RxData[3],2);
        MySpi_OLED_ShowNum(4,6,RxLength,2);

        delay_ms(200);
    }
}
